package cn.wowjoy.office.base;

import android.content.Context;
import android.content.pm.PackageManager;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.PermissionChecker;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import java.lang.reflect.Field;

import javax.inject.Inject;

import cn.wowjoy.office.R;
import cn.wowjoy.office.common.widget.MyToast;
import cn.wowjoy.office.data.remote.ApiException;
import cn.wowjoy.office.data.remote.ERROR;
import cn.wowjoy.office.data.remote.ExceptionEgine;
import cn.wowjoy.office.databinding.ErrorViewBinding;

import cn.wowjoy.office.utils.PreferenceManager;

/**
 * Created by Sherily on 2017/8/23.
 * Description: fragment with base function
 */
public abstract class BaseFragment<DB extends ViewDataBinding, VM extends BaseViewModel, P extends BasePresenter<VM>> extends Fragment {

    private boolean isInit = false;
    private boolean isStart = false;
    private Bundle savedInstanceState;
    public static final String INTENT_BOOLEAN_LAZYLOAD = "intent_boolean_lazyLoad";
    private boolean isLazyLoad = true;
    private View mRoot;

    private int isVisibleToUserState = VISIBLE_STATE_NOTSET;
    //未设置值
    private static final int VISIBLE_STATE_NOTSET = -1;
    //可见
    private static final int VISIBLE_STATE_VISIABLE = 1;
    //不可见
    private static final int VISIBLE_STATE_GONE = 0;

    protected DB binding;

    @Inject
    PreferenceManager preferenceManager;




    public BaseFragment() {
        // Required empty public constructor
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initializeInjector();
    }

    public boolean requestRuntimePermissions(final String[] permissions, final int requestCode) {
        boolean ret = true;
        for (String permission : permissions) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                ret &= (PermissionChecker.checkSelfPermission(getContext(), permission) == PermissionChecker.PERMISSION_GRANTED);
            else
                ret &= (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED);
        }
        if (ret) {
            return true;
        }
        boolean rationale = false;
        for (String permission : permissions) {
            rationale |= shouldShowRequestPermissionRationale(permission);
        }
        if (rationale) {
            if (getActivity() instanceof BaseActivity){
                Toast.makeText(getContext(),"请开启权限后使用",Toast.LENGTH_SHORT).show();
//                ((BaseActivity)getActivity()).makePrimaryColorSnackBar(R.string.common_request_permission, Snackbar.LENGTH_INDEFINITE)
//                        .setAction(R.string.common_allow_permission, new View.OnClickListener() {
//                            @Override
//                            public void onClick(View v) {
//                                requestPermissions(permissions, requestCode);
//                            }
//                        })
//                        .show();
            }
        } else {
            requestPermissions(permissions, requestCode);
        }
        return false;
    }
    @SuppressWarnings("unchecked")
    protected <T> T getComponent(Class<T> componentType) {
        return componentType.cast(((HashComponent<T>) getActivity()).getComponent());
    }

    protected void initializeInjector() {

    }
    public ApplicationComponent getApplicationComponent() {
        if (getActivity() instanceof BaseActivity) {
            return ((BaseActivity) getActivity()).getApplicationComponent();
        } else {
            throw new RuntimeException(getString(R.string.notice));
        }
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        this.savedInstanceState = savedInstanceState;
        binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
        mRoot = binding.getRoot();

        Bundle bundle = getArguments();
        if (bundle != null) {
            isLazyLoad = bundle.getBoolean(INTENT_BOOLEAN_LAZYLOAD, isLazyLoad);
        }

        //直接在每个子presenter通过dagger注入的方式进行自动关联viewmodel,activity。
        //为什么不直接getUserVisibleHint();而是通过自己存isVisibleToUserState变量判断
        //因为v4的25的版本 已经调用 setUserVisibleHint(true)，结果到这里getUserVisibleHint是false
        // （ps:看了FragmentManager源码Fragment被重新创建有直接赋值isVisibleToUser不知道是不是那里和之前v4有改动的地方）
        //所以我默认VISIBLE_STATE_NOTSET，之前没有调用setUserVisibleHint方法，就用系统的getUserVisibleHint，否则就用setUserVisibleHint后保存的值
        //总之就是调用了setUserVisibleHint 就使用setUserVisibleHint的值
        boolean isVisibleToUser;
        if (isVisibleToUserState == VISIBLE_STATE_NOTSET) {
            isVisibleToUser = getUserVisibleHint();
        } else {
            isVisibleToUser = isVisibleToUserState == VISIBLE_STATE_VISIABLE;
        }

        if (isLazyLoad) {
            if (isVisibleToUser) {
                isInit = true;
                onCreateViewLazy(savedInstanceState);
                lazyLoad();
            }
        } else {
            isInit = true;
            onCreateViewLazy(savedInstanceState);
            lazyLoad();
        }

        if(null == mRoot)
            return super.onCreateView(inflater, container, savedInstanceState);
        return mRoot;
    }


    private void lazyLoad(){
        if (null != getPresenter()) {
            getPresenter().onCreate();//onCreate属于懒加载
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        isVisibleToUserState = isVisibleToUser ? VISIBLE_STATE_VISIABLE : VISIBLE_STATE_GONE;
        if (isVisibleToUser && !isInit && mRoot != null) {
            isInit = true;
            onCreateViewLazy(savedInstanceState);
            onResumeLazy();
            lazyLoad();
        }
        if (isInit && mRoot != null) {
            if (isVisibleToUser) {
                isStart = true;
                onStartLazy();
            } else {
                isStart = false;
                onStopLazy();
            }
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 每个页面需要广播时候开启注册广播
     */
    protected void openBroadCast(){
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).openBroadCast();
        } else {
            throw new RuntimeException(getString(R.string.notice));
        }
    }


    /**
     * 关闭广播
     */
    protected void closeBroadCast(){
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).closeBroadCast();
        } else {
            throw new RuntimeException(getString(R.string.notice));
        }
    }

    /**
     * 扫码自定义逻辑实现入口
     * @param context
     * @param msg
     */
    protected void broaCast(Context context, String msg){
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).brodcast(context,msg);
        } else {
            throw new RuntimeException(getString(R.string.notice));
        }
    }


    private ErrorViewBinding errorViewBinding;

    /**
     * baseActivity中handleException(Exception e,boolean needErrorView):
     *统一处理exception，当needErrorView = true,是，需要在getErrorview中返回承载errorview的布局，
     *目前支持Framelayout，可以覆盖后面的结果页面。当needErrorView = false,用toast的形式提醒错误，401的状态下统一跳转至LoginActivity
     * @param e
     * @param needErrorview
     */
    public void handleException(Throwable e,boolean needErrorview){
        ApiException apiException = ExceptionEgine.handleException(e);
        if (apiException.getCode() == ERROR.UNAUTHORIZED){
            new MyToast(getContext()).showinfo(apiException.getMessage());
            preferenceManager.clearToken();
//            LoginActivity.startAndClearTask(getActivity());

        } else {
            if (needErrorview){
                createErrorView(apiException);
            } else {
                new MyToast(getContext()).showinfo(e.getMessage());
            }

        }
    }


    /**
     * 在每个子activity中实现，哪一块区域需要用，就返回哪块，目前只考虑FrameLayout
     * @return
     */
    protected ViewGroup getErrorViewRoot(){

        return  null;
    }

    protected void hideSoftInput(){
        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(binding.getRoot().getWindowToken(), 0);
    }

    /**
     * 记住，记住，记住，在需要errorview通过 getErrorViewRoot()返回承载errorview的布局，目前支持Framelayout
     * @param e
     */
    private void createErrorView( ApiException e){
        if (null != getErrorViewRoot()){
            if (null != errorViewBinding){
                removeErrorview();
            }
            hideSoftInput();
            LayoutInflater  inflater =  LayoutInflater.from(getErrorViewRoot().getContext());
            errorViewBinding = DataBindingUtil.inflate(inflater,R.layout.error_view,getErrorViewRoot(),false);
            errorViewBinding.getRoot().setClickable(true);
            switch (e.getCode()){
                case 404:
                    errorViewBinding.errorContent.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.error_404,0,0);
                    errorViewBinding.errorContent.setText(e.getMessage());
                    break;
                case 500:
                    errorViewBinding.errorContent.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.error_500,0,0);
                    errorViewBinding.errorContent.setText(e.getMessage());
                    break;
                case 1002:
                    errorViewBinding.errorContent.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.wi_fi,0,0);
                    errorViewBinding.errorContent.setText(e.getMessage());
                    break;
                default:
                    errorViewBinding.errorContent.setText(e.getMessage());
                    break;
            }
            errorViewBinding.errorContent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    refreshError();
                }
            });
            ViewGroup.LayoutParams layoutParams = getErrorViewRoot().getLayoutParams();
            getErrorViewRoot().addView(errorViewBinding.getRoot(),layoutParams);
        } else {
            //知道你们会忘记加布局，为了防止异常，有toast提醒
            new MyToast(getContext()).showinfo(e.getMessage());
        }


    }


    /**
     *在refreshError之后记住removeErroeView
     */
    protected void removeErrorview(){

        if (null != getErrorViewRoot()){
            getErrorViewRoot().removeView(errorViewBinding.getRoot());
        }
    }

    /**
     * errorView添加后，点击error图片即可重新请求相应的接口，进行处理
     */
    protected void refreshError(){
        removeErrorview();
        //具体页面实现请求对应接口渲染数据
    }


    @Deprecated
    @Override
    public final void onStart() {
        super.onStart();
        if (isInit && !isStart && getUserVisibleHint()) {
            isStart = true;
            onStartLazy();
        }
    }

    @Deprecated
    @Override
    public final void onStop() {
        super.onStop();
        if (isInit && isStart && getUserVisibleHint()) {
            isStart = false;
            onStopLazy();
        }
    }

    @Override
    @Deprecated
    public final void onResume() {
        super.onResume();
        if (isInit) {
            onResumeLazy();
        }
    }

    @Override
    @Deprecated
    public final void onPause() {
        super.onPause();
        if (isInit) {
            onPauseLazy();
        }
    }

    @Override
    @Deprecated
    public final void onDestroyView() {
        super.onDestroyView();
        mRoot = null;
        if (null != getPresenter()) getPresenter().onDestroy();
        if (isInit) {
            onDestroyViewLazy();
        }
        isInit = false;
    }

    protected void onResumeLazy(){}

    protected void onStartLazy(){}

    protected void onStopLazy(){}

    protected void onPauseLazy(){}

    protected void onDestroyViewLazy(){}



    protected abstract void onCreateViewLazy(Bundle savedInstanceState);

    protected abstract int getLayoutId();

    protected abstract P getPresenter();
    protected abstract VM getViewModel();

}
